package com.lfy.encrypt;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
 *  RSA算法 加密工具类
 *
 * @author <a href="https://www.lvfeiy.top">lvfeiyang</a>
 * @date 2024/5/16 18:42
 */
public class EncryptUtil {
    private static final String TYPE = "RSA";

    /**
     * 公钥加密
     * KeyFactory.getInstance 是非线程安全的。所以每次使用时都应该重新生成一个新的实例
     * @param content 加密前内容
     * @param publicKey 公钥
     * @return 加密后的内容
     * @throws Exception exception
     */
    public static String encryptByPublicKey(String content, String publicKey) throws Exception {
        // 公钥解码
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
        // 公钥转换
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        // 密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        // 公钥对象
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
        // 加密器
        Cipher cipher = Cipher.getInstance(TYPE);
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 加密
        byte[] bytes = cipher.doFinal(content.getBytes());
        // 编码
        return Base64.getEncoder().encodeToString(bytes);
    }

    /**
     * 公钥解密
     * @param content 加密内容
     * @param publicKey 公钥
     * @return 解密后的内容
     * @throws Exception exception
     */
    public static String decryptByPublicKey(String content, String publicKey) throws Exception {
        // 公钥解码
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
        // 公钥转换
        X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        // 密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        // 公钥对象
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(publicKeySpec);
        // 加密器
        Cipher cipher = Cipher.getInstance(TYPE);
        // 初始化加密器
        cipher.init(Cipher.DECRYPT_MODE, key);
        // 解密
        byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(content));
        // 解码
        return new String(bytes, StandardCharsets.UTF_8);
    }
    /**
     * 私钥加密
     * @param content 加密前内容
     * @param privateKey 私钥
     * @return 加密后的内容
     * @throws Exception exception
     */
    public static String encryptByPrivateKey(String content, String privateKey) throws Exception {
        // 私钥解码
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
        // 私钥转换
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        // 密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        // 私钥对象
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
        // 加密器
        Cipher cipher = Cipher.getInstance(TYPE);
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // 加密
        byte[] bytes = cipher.doFinal(content.getBytes());
        // 编码
        return Base64.getEncoder().encodeToString(bytes);

    }
    /**
     * 私钥解密
     * @param content 加密内容
     * @param privateKey 私钥
     * @return 解密后的内容
     * @throws Exception exception
     */
    public static String decryptByPrivateKey(String content, String privateKey) throws Exception {
        // 私钥解码
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey);
        // 私钥转换
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        // 密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(TYPE);
        // 私钥对象
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);
        // 加密器
        Cipher cipher = Cipher.getInstance(TYPE);
        // 初始化加密器
        cipher.init(Cipher.DECRYPT_MODE, key);
        // 解密
        byte[] bytes = cipher.doFinal(Base64.getDecoder().decode(content));
        // 解码
        return new String(bytes, StandardCharsets.UTF_8);
    }


    public static void main(String[] args) throws Exception {
        test();
    }
    private static void test()  throws Exception{

        KeyPairGenerator instance = KeyPairGenerator.getInstance(TYPE);
        KeyPair keyPair = instance.generateKeyPair();
        //私钥
        PrivateKey privateKey = keyPair.getPrivate();
        //公钥
        PublicKey publicKey = keyPair.getPublic();
        RSAPublicKey key1 = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey key2 = (RSAPrivateKey) keyPair.getPrivate();

        //转码
        byte[] publicKeyBytes = publicKey.getEncoded();
        byte[] privateKeyBytes = privateKey.getEncoded();
        String publicKeyStr = Base64.getEncoder().encodeToString(publicKeyBytes);
        String privateKeyStr = Base64.getEncoder().encodeToString(privateKeyBytes);

        System.out.println("公钥：" + publicKeyStr);
        System.out.println("私钥：" + privateKeyStr);

        String password = "123456";
        //公钥加密
        String encrypt = encryptByPublicKey(password, publicKeyStr);
        System.out.println("公钥加密后：" + encrypt);
        //私钥解密
        String decrypt = decryptByPrivateKey(encrypt, privateKeyStr);
        System.out.println("私钥解密后：" + decrypt);
        //私钥加密
        String s = encryptByPrivateKey(password, privateKeyStr);
        System.out.println("私钥加密后：" + s);
        //公钥解密
        String s1 = decryptByPublicKey(s, publicKeyStr);
        System.out.println("公钥解密后：" + s1);
    }
}
